function varargout = TLDiscreteTransferFcnDlg(action,varargin)

% TL_DISCRETETRANSFERFCN_DLG manages the user interface for TargetLink Discrete Transfer Function block
%
% SYNTAX dlgInfo = TLDiscretetransferfcnDlg('GetDlgInfo');
%   gets dialog info of TargetLink Discrete Transfer Function block
%
%   INPUT ARGUMENTS
%   -/-      
%
%   OUTPUT ARGUMENTS
%   dlgInfo     dialog information contains pageNames etc.
%
% SYNTAX [sheetDims, ctrlPos] = TLDiscretetransferfcnDlg('CtrlPositions', pageName, commonGeom, dlgInfo, sheetDims);
%   calculates the control positions of all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   commonGeom      common geometry data
%   dlgInfo         dialog information contains pageNames etc.
%   sheetDims       dimension of sheet
%
%   OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% SYNTAX dlgdata = TLDiscretetransferfcnDlg('Create', pageName, dlgfig, dlgdata);
%   creates all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX [dlgdata,bModified] = TLDiscretetransferfcnDlg('Manage', pageName, dlgfig, dlgdata, pageAction);
%   manages all actions of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageAction      modified control of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       flag = 1, if dialog data are modified, =0 otherwise
%
% SYNTAX dlgdata = TLDiscretetransferfcnDlg('Update', dlgfig, dlgdata, pageNum);
%   updates all controls of dialog page: <pageNum>
%
%   INPUT ARGUMENTS
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageNum         number of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX TLDiscretetransferfcnDlg('Apply', dlgfig, dlgdata);
%   writes current blockdata to block and DD
%
%   INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
%   OUTPUT ARGUMENTS
%   - / -


% Author(s): D. Andoleit, T. Pietzsch
% $RCSfile: TLDiscretetransferfcnDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/SimulinkBlocksets/TLBlocksets/CommonBlockset/CommonBlockset_SimBlocksUI/Sources/MSrc/project.pj $
% $Revision: 1.25 $
% $Date: 2011/08/22 10:34:17MESZ $
%
% Copyright ?2011 dSPACE GmbH. All rights reserved.


switch action

    case 'GetDlgInfo'
        hBlock = varargin{1};
        dlgInfo = tl_get_dlginfodefaults('tlsim');
        titleName = 'Discrete Transfer Function';
        pathinfo = tl_pathinfo(hBlock);
        dlgInfo.title = sprintf('TargetLink %s: %s', titleName, pathinfo.shortDisplayName);
        dlgInfo.pageNames   = {
            'Output', ...
            'Coefficients', ...
            'Logging & Autoscaling', ...
            'Documentation'};
        varargout{1} = dlgInfo;
        varargout{2} = get_tlcg_data(hBlock);

    case 'CtrlPositions'
        pageName     = varargin{1};
        commonGeom   = varargin{2};
        sheetDims    = varargin{4};
        switch pageName
            case 'Output'
                [sheetDims, ctrlPos] = FcnOutputCtrlPositions(commonGeom);

            case 'Coefficients'
                [sheetDims, ctrlPos] = FcnCoeffCtrlPositions(commonGeom);

            case 'Logging & Autoscaling'
                excludedCtrls = {'plotEdit'};
                [sheetDims, ctrlPos] = ...
                    TLManageLoggingCtrls('calcCtrls', commonGeom, sheetDims, excludedCtrls);

            case 'Documentation'
                bTblBlock = 0;
                bCodeComment = 1;
                [sheetDims,ctrlPos] = TLManageDocCtrls('ctrlpos', commonGeom, ...
                    sheetDims, bCodeComment, bTblBlock);
        end
        varargout{1} = sheetDims;
        varargout{2} = ctrlPos;

    case 'Create',
        pageName = varargin{1};
        dlgfig   = varargin{2};
        dlgdata  = varargin{3};
        pageNum  = strmatch(pageName, dlgdata.pageNames, 'exact');
        switch pageName
            case 'Output'
                dlgdata = FcnCreateOutputPage(pageNum, dlgfig, dlgdata);

            case 'Coefficients'
                dlgdata =  FcnCreateCoeffPage(pageNum, dlgfig, dlgdata);

            case 'Logging & Autoscaling'
                dlgdata = TLManageLoggingCtrls('create',pageNum,dlgfig,dlgdata);

            case 'Documentation'
                dlgdata = TLManageDocCtrls('create',pageNum,dlgfig,dlgdata);
        end
        dlgdata.pageData{pageNum}.ctrlPos = [];
        varargout{1} = dlgdata;

    case 'Manage',
        pageName   = varargin{1};
        dlgfig     = varargin{2};
        dlgdata    = varargin{3};
        pageAction = varargin{4};
        pageNum    = strmatch(pageName, dlgdata.pageNames, 'exact');
        switch pageName
            case 'Output'
                [dlgdata, bModified] = ...
                    FcnManageOutputPage(pageNum, dlgfig, dlgdata, pageAction);

            case 'Coefficients'
                [dlgdata, bModified] = ...
                    FcnManageCoeffPage(pageNum, dlgfig, dlgdata, pageAction);

            case 'Logging & Autoscaling'
                [dlgdata, bModified] = ...
                    TLManageLoggingCtrls('manage', pageNum, dlgdata, pageAction, 'logdata');

            case 'Documentation'
                [dlgdata, bModified] = TLManageDocCtrls( ...
                    'callback', pageNum, dlgfig, dlgdata, pageAction);
        end
        varargout{1} = dlgdata;
        varargout{2} = bModified;

    case 'ManageSystemIcons',
        dlgfig     = varargin{1};
        dlgdata    = varargin{2};
        pageAction = varargin{3};
        [dlgdata, bModified] = FcnManageSystemIcons(dlgfig,dlgdata,pageAction);
        varargout{1} = dlgdata;
        varargout{2} = bModified;

    case 'Update'
        dlgfig      = varargin{1};
        dlgdata     = varargin{2};
        if isstruct(varargin{3})
            % update tool data from scaling tool
            dlgdata.pageData{1}.toolData = varargin{3};
            FcnCheckHeadroom(dlgdata);
            pageNum = dlgdata.CurrentPageNum;
        else
            % update dialog
            pageNum = varargin{3};
        end
        switch pageNum
            case 1
                % output page
                dlgdata = FcnUpdateOutputPage(dlgdata, dlgfig, pageNum);

            case 2
                % coefficient page
                dlgdata = FcnUpdateCoeffPage(dlgdata, dlgfig, pageNum);

            case 3
                % logging page
                dlgdata =  FcnUpdataLoggingControls(pageNum, dlgfig, dlgdata);

            case 4
                % documentation page
                TLManageDocCtrls('update', pageNum, dlgfig, dlgdata);
        end

        if ishandle(dlgdata.toolfig)
            dlgdata = FcnUpdateTFTool(dlgdata);
        end

        varargout = {dlgdata};

    case 'Apply'
        dlgdata  = varargin{2};
        bContinue = varargin{3};    % =0 'apply', =1 'close'

        % set batchmode to avoid message boxes
        ds_error_set('BatchMode','on');
        [ok,msg] = FcnChkTransferFcn(dlgdata);
        ds_error_set('BatchMode','off');
        if ~ok
            msg = [msg 'Do you really want to apply these inconsistent data?'];
            msg = [msg char(10) 'Click ''Yes'' to write data '];
            msg = [msg 'or ''No'' to continue editing.'];
            btn = {'Yes','No'};
            [selection,hMsgBox] = ds_msgbox('Title', 'Data inconsistency!', ...
                'Message', msg, ...
                'Style',   'question', ...
                'Button',  btn, ...
                'Default', 'No', ...
                'Close',   'manual');
            while(hMsgBox)
                switch selection
                    case 'Yes'
                        delete(hMsgBox);
                        try
                            % write current data to block
                            set_tlcg_data(dlgdata.model,dlgdata.data);
                            bContinue = 1;
                        catch
                        end
                        break
                    case 'No'
                        if ishandle(hMsgBox)
                            % handle default button
                            delete(hMsgBox);
                        end
                        bContinue = 0;
                        break
                end
            end
        else
            [dlgdata, bContinue] = tl_apply_blockdata(dlgdata, bContinue);
        end
        varargout{1} = dlgdata;
        varargout{2} = bContinue;

    otherwise
        error(['Invalid action: "' action '"']);
end


%-----------------------------------------------------------------------------------------
% FcnManageSystemIcons manage actions of toolbar icons
%
% INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   action      action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageSystemIcons(dlgfig, dlgdata, action) %#ok

bModified = false;
switch action
    case 'EditCode'
        % look for associated production code file
        [codefile,blockstr] = get_codefile(dlgdata.model);
        if ~isempty(codefile)
            codeedit(codefile,blockstr);
        end

    case 'ViewCode'
        switch dlgdata.pageNames{dlgdata.CurrentPageNum}
            case 'Coefficients'
                blockVar{1} = 'num';
                blockVar{2} = 'denom';
                idx = get(dlgdata.pageData{2}.children.selectPopup,'Value');
                tl_create_links_to_model('ShowDeclaration',dlgdata.model, blockVar{idx});
            otherwise
                blockVar = 'output';
                tl_create_links_to_model('ShowComputation',dlgdata.model, blockVar);
        end

    otherwise
        error('Invalid callback');

end % switch(action)


%-----------------------------------------------------------------------------------------
% FcnOutputCtrlPositions calculates positions for all controls on output page
%
% INPUT ARGUMENTS
%   commonGeom      common geometrie information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims, ctrlPos] = FcnOutputCtrlPositions(commonGeom)

% create standard output controls
excludedCtrls = {'inheritproperties', 'width', 'element', 'scalarExp'};
[sheetDims, ctrlPos, col] = ...
    tl_calc_ctrls_positions(commonGeom, excludedCtrls);

% get sizes for further controls
strings_and_styles = { ...
    'Sample time:',         'text';...
    ' Scaling Tool ... ',   'pushbutton'};

[stepsizeLabelSize, ...
    tftoolButtonSize] = ...
    ds_get_uicontrol_sizes(commonGeom, strings_and_styles);

%---------------------------------------
% 1st row
cy = commonGeom.frameBottomEdgeBuffer;

% scaling tool button
cx = col(7);
ctrlPos.tftoolButton = [cx cy tftoolButtonSize];

% stepsize label
cx = col(1);
ctrlPos.stepsizeLabel = [cx cy stepsizeLabelSize];

% stepsize edit field
cx = col(2);
ctrlPos.stepsizeEdit = [cx cy ctrlPos.varEdit(3:4)];

% increase sheet dimensions
sheetDims(2) = sheetDims(2) ...
    + ctrlPos.addoptGroupbox(4) ...
    + commonGeom.textHeight;


%-----------------------------------------------------------------------------------------
% FcnCreateOutputPage creates the figure window
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateOutputPage(pageNum, dlgfig, dlgdata)

dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata);
dlgdata = TLManageScalingCtrls('create', pageNum, dlgfig, dlgdata);

Children = dlgdata.pageData{pageNum}.children;
ctrlPos = dlgdata.pageData{pageNum}.ctrlPos;
pageName = dlgdata.pageNames{pageNum};

data = dlgdata.data;

% get tool data
blockData = get_param(dlgdata.model, 'UserData');
if isfield(blockData, 'toolData')
    % retrieve toolData from block
    toolData = blockData.toolData;
else
    % default values for user inputs in tf tool
    toolData = FcnGetDefaultToolData(dlgdata);
end
dlgdata.pageData{pageNum}.toolData = toolData;

% create the addoptGroupbox which will contain scaling tool options
Children.addoptGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Sample time and scaling tool'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.addoptGroupbox);

% scale tool button
Children.tftoolButton = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'pushbutton', ...
    'String',             ' Scaling Tool ... ', ...
    'Enable',             flag2str(ds_isa(['/Pool/Typedefs/' data.output.type], 'integertype') & dlgdata.bIsFullVs), ...
    'Position',           ctrlPos.tftoolButton, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''tftoolButton'')',pageName));

% stepsize controls
Children.stepsizeLabel = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'text', ...
    'String',             'Sample time:', ...
    'Position',           ctrlPos.stepsizeLabel);

Children.stepsizeEdit = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'BackgroundColor',    'w', ...
    'Style',              'edit', ...
    'String',             data.dt, ...
    'Position',           ctrlPos.stepsizeEdit, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''stepsizeEdit'')',pageName));

dlgdata.pageData{pageNum}.children = Children;


%-----------------------------------------------------------------------------------------
% FcnManageOutputPage manages control actions of output page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata,bModified] = FcnManageOutputPage(pageNum,dlgfig,dlgdata,action)

bModified = 0;
Children  = dlgdata.pageData{pageNum}.children;

switch action
    case 'tftoolButton'
        if ishandle(dlgdata.toolfig)
            % put tool dialog into the foreground
            figure(dlgdata.toolfig);
        else
            % create tool dialog
            [ok, msg] = FcnChkTransferFcn(dlgdata);
            if ok
% 							hdlgfig = get(dlgfig,'Parent');
                dlgdata.toolfig = dstabdlg( ...
                    'create', 'TLTftoolDlg', dlgdata.model, 'Transfer Function Tool', dlgfig);
                bModified = 1;
            else
                ds_error_msg({'Transfer Function Scaling Tool cannot be opened:' msg}, ...
                    'Title', 'Transfer Function Scaling Tool', ...
                    'PrintMessage', 'no', ...
                    'RegisterMessage', 'no');
                bModified = 0;
            end
        end

    case 'stepsizeEdit'
        stepsizestr = get(Children.stepsizeEdit, 'String');
        if ~isempty(stepsizestr)
            dlgdata.data.dt = stepsizestr;
        else
            beep;
        end
        bModified = 1;

    otherwise
        [dlgdata, bModified1] = ...
            TLManageVariableCtrls('manage',pageNum,dlgfig,dlgdata,action,'output');
        [dlgdata,bModified2] = ...
            TLManageScalingCtrls('manage',pageNum,dlgfig,dlgdata,action,'output');
        bModified = bModified1 || bModified2;

end % switch action


%--------------------------------------------------------------------------
% FcnUpdateOutputPage updates the controls of the output tab
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdateOutputPage(dlgdata, dlgfig, pageNum)

% default status of controls
stepsizeEditCtrlStatus = struct('enable', 'on', 'string', '-1');
tftoolButtonCtrlStatus = struct('enable', 'on');

dlgdata = TLManageVariableCtrls('update', pageNum, dlgdata, 'output');
dlgdata = TLManageScalingCtrls('update', pageNum, dlgdata, 'output', []);

% update control status
stepsizeEditCtrlStatus.string = dlgdata.data.dt;

tftoolButtonCtrlStatus.enable = flag2str(dlgdata.bIsFullVs && ...
    ds_isa(['/Pool/Typedefs/' dlgdata.data.output.type], 'integertype'));

Children = dlgdata.pageData{pageNum}.children;
ctrlsList = {'stepsizeEdit', 'tftoolButton'};
for ctrlsNo = 1:length(ctrlsList)
    ctrl = Children.(ctrlsList{ctrlsNo});
    UserData = get(ctrl, 'UserData');
    UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
    set(ctrl, 'UserData', UserData);
end

TLManageVariableCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLManageScalingCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLSetCtrlsStatus(dlgfig, Children, ctrlsList)


%-----------------------------------------------------------------------------------------
% FcnCoeffCtrlPositions calculates positions for all controls on coefficients page
%
% INPUT ARGUMENTS
%   commonGeom      common geometrie information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims, ctrlPos] = FcnCoeffCtrlPositions(commonGeom)

% get sizes of standard controls
excludedCtrls = {'calcranges', 'saturate', 'inheritproperties'};
[sheetDims, ctrlPos, col, colDelta, rowDelta] = ...
    tl_calc_ctrls_positions(commonGeom, excludedCtrls);

% determine sizes for further controls
strings_and_styles = {...
    'Select:',                 'text';...
    'Numerator:',              'text';...
    'Denominator:',            'text';...
    'Keep vector structure',   'checkbox';...
    'Scale Coefficients',      'pushbutton'; ...
    'Use value of Data Dictionary variable', 'checkbox'};

[selectLabelSize, ...
    numLabelSize, ...
    denLabelSize, ...
    veckeepCheckboxSize, ...
    autoscaleButtonSize, ...
    useDDValueCheckboxSize] = ...
    ds_get_uicontrol_sizes(commonGeom,strings_and_styles);

% calculate extra space needed for select popup
dy = commonGeom.editHeight + rowDelta;

% enlarge tlcgGroupbox and move addoptGroupbox
ctrlPos.tlcgoptGroupbox(4) = ctrlPos.tlcgoptGroupbox(4) + dy;
ctrlPos.addoptGroupbox(2)   = ctrlPos.addoptGroupbox(2)   + dy;

% define new height for addoptGroupbox
ctrlPos.addoptGroupbox(4) = commonGeom.editHeight ...
    + commonGeom.checkboxHeight ...
    + 2*rowDelta ...
    + commonGeom.frameBottomEdgeBuffer ...
    + commonGeom.frameTopEdgeBuffer;

% supplement tlcgGroupbox
cy = ctrlPos.descLabel(2) + commonGeom.editHeight + rowDelta;

% select label
cx = col(1);
ctrlPos.selectLabel = [cx cy selectLabelSize];

% select popup
cx = col(2);
ctrlPos.selectPopup = [cx cy ctrlPos.lsbEdit(3:4)];

% keep vector structure checkbox
cx = col(4);
ctrlPos.veckeepCheckbox = [cx cy veckeepCheckboxSize];

% scale coefficients button
cx = col(7);
ctrlPos.autoscaleButton = [cx cy autoscaleButtonSize];

%---------------------------------------
% 2nd row
cy = commonGeom.frameBottomEdgeBuffer;

cx = col(2);
ctrlPos.numDDValueCheckbox = [cx, cy, useDDValueCheckboxSize];

cx = col(6);
ctrlPos.denDDValueCheckbox = [cx, cy, useDDValueCheckboxSize];

%---------------------------------------
% 1st row
cy = cy + commonGeom.editHeight + rowDelta;

% numerator label
cx = col(1);
ctrlPos.numLabel = [cx cy numLabelSize];

% numerator edit field
cx = col(2);
ctrlPos.numEdit = [cx cy ctrlPos.varEdit(3:4)];

% denominator label
cx = col(6) - denLabelSize(1) - colDelta / 3;
ctrlPos.denLabel = [cx cy denLabelSize];

% denominator edit field
cx = col(6);
ctrlPos.denEdit = [cx cy ctrlPos.varEdit(3:4)];

% increase sheet dimensions
sheetDims(2) = sheetDims(2) + ...
    + ctrlPos.addoptGroupbox(4) ...
    + commonGeom.textHeight ...
    + dy;


%-----------------------------------------------------------------------------------------
% FcnCreateCoeffPage creates the coefficients page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateCoeffPage(pageNum,dlgfig,dlgdata)

% create standard controls
dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata);
dlgdata = TLManageScalingCtrls('create', pageNum, dlgfig, dlgdata);

% prepare some needed data
Children = dlgdata.pageData{pageNum}.children;
ctrlPos = dlgdata.pageData{pageNum}.ctrlPos;
pageName = dlgdata.pageNames{pageNum};

% select controls
Children.selectLabel = uicontrol( ...
    'Parent',             Children.tlcgoptGroupbox, ...
    'String',             'Select:', ...
    'Style',              'text', ...
    'Position',           ctrlPos.selectLabel);

Children.selectPopup = uicontrol( ...
    'Parent',             Children.tlcgoptGroupbox, ...
    'Style',              'Popupmenu', ...
    'String',             {'numerator'}, ...
    'BackgroundColor',    'w', ...
    'Position',           ctrlPos.selectPopup, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''selectPopup'')',pageName));

% keep current vector structure checkbox
Children.veckeepCheckbox = uicontrol( ...
    'Parent',             Children.tlcgoptGroupbox, ...
    'Style',              'checkbox', ...
    'String',             'Keep vector structure', ...
    'Position',           ctrlPos.veckeepCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''veckeepCheckbox'')',pageName));

Children.autoscaleButton = uicontrol( ...
    'Parent',             Children.tlcgoptGroupbox, ...
    'Style',              'pushbutton', ...
    'String',             'Scale Coefficients', ...
    'Position',           ctrlPos.autoscaleButton, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''autoscaleButton'')',pageName));

% create the addoptGroupbox which will contain coefficient options
Children.addoptGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Coefficients'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.addoptGroupbox);

% coefficients controls
Children.numLabel = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'String',             'Numerator:', ...
    'Style',              'text', ...
    'Position',           ctrlPos.numLabel);

Children.numEdit = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'edit', ...
    'BackgroundColor',    'w', ...
    'Position',           ctrlPos.numEdit, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''numEdit'')',pageName));

Children.denLabel = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'String',             'Denominator:', ...
    'Style',              'text', ...
    'Position',           ctrlPos.denLabel);

Children.denEdit = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'edit', ...
    'BackgroundColor',    'w', ...
    'Position',           ctrlPos.denEdit, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''denEdit'')',pageName));

Children.numDDValueCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'checkbox', ...
    'String',             'Use value of Data Dictionary variable', ...
    'Position',           ctrlPos.numDDValueCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''numDDValueCheckbox'')',pageName));

Children.denDDValueCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'checkbox', ...
    'String',             'Use value of Data Dictionary variable', ...
    'Position',           ctrlPos.denDDValueCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''denDDValueCheckbox'')',pageName));

dlgdata.pageData{pageNum}.children = Children;


%-----------------------------------------------------------------------------------------
% FcnManageCoeffPage manages control actions of coefficients page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageCoeffPage(pageNum, dlgfig, dlgdata, pageAction)

Children = dlgdata.pageData{pageNum}.children;
selectIdx = get(Children.selectPopup, 'Value');
switch selectIdx
    case 1
        field = 'num';
    case 2
        field = 'denom';
end

switch pageAction
    case 'veckeepCheckbox'
        dlgdata.data.matkeep = get(Children.veckeepCheckbox, 'Value');
        bModified = true;

    case {'numEdit', 'denEdit'}
        if strcmp(pageAction, 'numEdit')
            varName = 'num';
        else
            varName = 'denom';
        end
        coeff = tl_deblank(get(Children.(pageAction), 'String'), 2);
        if ~isempty(coeff)
            if strcmp(coeff, 'ddv')
                if isempty(dlgdata.data.(varName).variable)
                    beep
                else
                    dlgdata.data.(varName).value = ['ddv(''', dlgdata.data.(varName).variable, ''')'];
                    dlgdata.data.(varName).useddvariablevalue = true;
                end
            else
                dlgdata.data.(varName).value = coeff;
            end
        else
            beep;
        end
        bModified = true;
    
    case {'numDDValueCheckbox', 'denDDValueCheckbox'}
        if strncmp(pageAction, 'num', 3)
            varName = 'num';
        else
            varName = 'denom';
        end
        if get(Children.(pageAction), 'Value')
            dlgdata.data.(varName).value = ['ddv(''', dlgdata.data.(varName).variable, ''')'];
            dlgdata.data.(varName).useddvariablevalue = true;
        else
            dlgdata.data.(varName).useddvariablevalue = false;
        end
        bModified = true;

    case 'selectPopup'
        bModified = true;

    case 'autoscaleButton'
        options.selectDatatypeSign = 'yes';
        options.minimizeWordWidth  = 'yes';
        ds_error_none;
        [dlgdata.data, bModified, msgstruct] = tl_scale_parameters( ...
            dlgdata.model, dlgdata.data, options, field);
        ds_error_register(msgstruct);
        ds_msgdlg('Update', ...
            'Title', ['Scaling of ' get_tlsubsystempath(dlgdata.model) '->' field], ...
            'ShowErrors','yes', ...
            'ShowNotes','yes', ...
            'ShowWarnings','yes');
        % tl_scale_parameters doesn't care about scalar expansion, so we switch
        % it off here (just like TL 2.2 did with the 'Same scaling' flag.)
        if dlgdata.data.(field).width ~= 1
            dlgdata.extdata.(field).scalarExp = 0;
        end
        
    otherwise
        [dlgdata, bModified1] = ...
            TLManageVariableCtrls('manage', pageNum, dlgfig, dlgdata, pageAction, field);

        if bModified1 && any(strcmp(pageAction, {'classEdit', 'classSelectButton'}))
            % make sure all 4 matrices have the same variable class
            dlgdata.data.num.class = dlgdata.data.(field).class;
            dlgdata.data.denom.class = dlgdata.data.(field).class;
        end

        [dlgdata,bModified2] = ...
            TLManageScalingCtrls('manage', pageNum, dlgfig, dlgdata, pageAction, field);

        bModified = bModified1 || bModified2;

end % switch pageAction


%--------------------------------------------------------------------------
% FcnUpdateCoeffPage updates the controls of the coefficients tab
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdateCoeffPage(dlgdata, dlgfig, pageNum)

% default control status
numEditCtrlStatus = struct('enable', 'on');
denEditCtrlStatus = struct('enable', 'on');
selectPopupCtrlStatus = struct(...
    'enable', 'on', ...
    'value', 1, ...
    'string', {{'numerator'; 'denominator'}});
veckeepCheckboxCtrlStatus = struct('enable', 'on');
autoscaleButtonCtrlStatus = struct('enable', 'on');

Children = dlgdata.pageData{pageNum}.children;
selectIdx = get(Children.selectPopup, 'Value');
switch selectIdx
    case 1
        field = 'num';
    case 2
        field = 'denom';
end
selectPopupCtrlStatus.value = selectIdx;

% invoke standard update methods
dlgdata = TLManageVariableCtrls('update', pageNum, dlgdata, field);
[fieldValue, constraint, bCompliant] = tl_get_param_constraints(dlgdata.data.(field), dlgdata.extdata.(field));
dlgdata = TLManageScalingCtrls('update', pageNum, dlgdata, field, constraint);

% value edit fields
numEditCtrlStatus.string = dlgdata.data.num.value;
denEditCtrlStatus.string = dlgdata.data.denom.value;

% status of ddv checkbox
numDDValueCheckboxCtrlStatus.enable = flag2str(~isempty(dlgdata.data.num.variable));
numDDValueCheckboxCtrlStatus.value = dlgdata.data.num.useddvariablevalue;
if dlgdata.data.num.useddvariablevalue
    numEditCtrlStatus.enable = 'inactive';
end
denDDValueCheckboxCtrlStatus.enable = flag2str(~isempty(dlgdata.data.denom.variable));
denDDValueCheckboxCtrlStatus.value = dlgdata.data.denom.useddvariablevalue;
if dlgdata.data.denom.useddvariablevalue
    denEditCtrlStatus.enable = 'inactive';
end

% check only width of second parameter
switch selectIdx
    case 1
        if ~bCompliant
            numEditCtrlStatus.iserror = 1;
        end
        denomValue = tl_ensure_param_vector(dlgdata.data.denom.value);
        if ~isempty(denomValue) && ~isequal(dlgdata.data.denom.width, -1) ...
                && numel(denomValue) > 1 && numel(denomValue) ~= dlgdata.data.denom.width
            denEditCtrlStatus.iserror = 1;
        end
    case 2
        if ~bCompliant
            denEditCtrlStatus.iserror = 1;
        end
        numValue = tl_ensure_param_vector(dlgdata.data.num.value);
        if ~isempty(numValue) && ~isequal(dlgdata.data.num.width, -1) ...
                && numel(numValue) > 1 && numel(numValue) ~= dlgdata.data.num.width
            numEditCtrlStatus.iserror = 1;
        end
end
veckeepCheckboxCtrlStatus.value = dlgdata.data.matkeep;

% for parameters there are no simulated ranges. Instead, write min/max of coeff
% value
simulatedLabelCtrlStatus = tl_get_control_userdata(Children.simulatedLabel);
upperSimulatedValueCtrlStatus = tl_get_control_userdata(Children.upperSimulatedValue);
lowerSimulatedValueCtrlStatus = tl_get_control_userdata(Children.lowerSimulatedValue);
if dlgdata.extdata.(field).scalarExp
    simulatedLabelCtrlStatus.string = 'of vector';
else
    simulatedLabelCtrlStatus.string = 'of element';
end

widthUpButtonCtrlStatus = tl_get_control_userdata(Children.widthUpButton);
if selectIdx == 1 && dlgdata.data.num.width == dlgdata.data.denom.width
    widthUpButtonCtrlStatus.enable = 'off';
end

if ~strcmp(dlgdata.data.(field).class, 'default')
    % disable 'keep vector structure' checkbox if variable class has value_param
    % or ref_param scope
    [bExist, hClass] = dsdd('Exist', ['/Pool/VariableClasses/', ...
        dlgdata.data.(field).class], 'ObjectKind', 'VariableClass');
    if bExist
        scope = dsdd('GetScope', hClass);
        bMatkeepEnable = ~any(strcmp({'value_param', 'ref_param'}, scope));
    else
        bMatkeepEnable = 0;
    end

    veckeepCheckboxCtrlStatus.enable = flag2str(bMatkeepEnable & dlgdata.bIsFullVs);
    veckeepCheckboxCtrlStatus.value = dlgdata.data.matkeep & bMatkeepEnable;

    if isempty(constraint)
        minstr = 'n.a.';
        maxstr = 'n.a.';
    else
        minstr = sprintf('%0.6g', min(constraint));
        maxstr = sprintf('%0.6g', max(constraint));
    end

    upperSimulatedValueCtrlStatus.string = maxstr;
    lowerSimulatedValueCtrlStatus.string = minstr;

    typeString = ['/Pool/Typedefs/' dlgdata.data.(field).type];
    buttonEnable = dlgdata.bIsFullVs && ...
        all(isfinite(constraint)) && ...
        ds_isa(typeString, 'integertype');
else
    veckeepCheckboxCtrlStatus.enable = 'off';
    veckeepCheckboxCtrlStatus.value = 0;
    buttonEnable = 0;
end
autoscaleButtonCtrlStatus.enable = flag2str(buttonEnable);


extraCtrlsList = {
    'numEdit', ...
    'denEdit',...
    'veckeepCheckbox', ...
    'selectPopup', ...
    'autoscaleButton', ...
    'numDDValueCheckbox', ...
    'denDDValueCheckbox'};
standardCtrlsList = {
    'widthUpButton', ...
    'simulatedLabel', ...
    'upperSimulatedValue', ...
    'lowerSimulatedValue'
    };
ctrlsList = [extraCtrlsList standardCtrlsList];
for ctrlsNo=1:length(ctrlsList)
    ctrl = Children.(ctrlsList{ctrlsNo});
    UserData = get(ctrl, 'UserData');
    UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
    set(ctrl, 'UserData', UserData);
end

% set control status of standard controls
TLManageVariableCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLManageScalingCtrls('setCtrls', pageNum, dlgfig, dlgdata);

% set status of coeff controls
TLSetCtrlsStatus(dlgfig, Children, extraCtrlsList)


%-----------------------------------------------------------------------------------------
% FcnUpdataLoggingControls updates output page
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%--------------------------------------------------------------------------
function dlgdata =  FcnUpdataLoggingControls(pageNum,dlgfig,dlgdata)

dlgdata =  TLManageLoggingCtrls('update',pageNum,dlgdata,'logdata','output');

Children = dlgdata.pageData{pageNum}.children;

% overwrite control status of offset
keepParamOffsetCheckboxCtrlStatus     = struct('enable', 'inactive', 'value', 1);   %#ok
ctrlsList = {'keepParamOffsetCheckbox'};
for ctrlsNo = 1:length(ctrlsList)
    ctrl = Children.(ctrlsList{ctrlsNo});
    UserData = get(ctrl, 'UserData');
    if strcmp(UserData.ctrlStatus.enable, 'on')
        UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
        set(ctrl, 'UserData', UserData);
    end
end

TLManageLoggingCtrls('setCtrls',pageNum, dlgfig, dlgdata);


%--------------------------------------------------------------------------
% FcnUpdateTFTool updates scaling tool
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdateTFTool(dlgdata)

pageNum = 1;
ok = 1;

% check if type is one of TargetLink's basetypes
[bExist,hTypedef] = dsdd('Exist',['Pool/Typedefs/',dlgdata.data.output.type], ...
    'ObjectKind',             'Typedef');
if bExist,
    bIsBaseType = dsdd('GetIsBaseType',hTypedef);
else
    bIsBaseType = 0;
end

if ~FcnChkTransferFcn(dlgdata)
    errorStr = 'You have modified the system.';
    ok = 0;
elseif ~bIsBaseType,
    errorStr = 'You have selected a non-basic datatype.';
    % transfer function scaling tool button
    set(dlgdata.pageData{1}.children.tftoolButton, ...
        'Enable','off');
    ok = 0;
end
if ok
    tl_tftool_dlg('UpdateData', dlgdata.toolfig, dlgdata.data);
else
    ds_error_msg({errorStr 'The Transfer-Function Scaling Tool will be closed.'}, ...
        'Title','Transfer Function Scaling Tool', ...
        'PrintMessage','no', ...
        'RegisterMessage','no');
    if ishandle(dlgdata.toolfig),
        tooldlgdata = get(dlgdata.toolfig,'UserData');
        delete(dlgdata.toolfig);
        if ishandle(tooldlgdata.toolfig)
            delete(tooldlgdata.toolfig);
        end
        dlgdata.pageData{pageNum}.toolData = tooldlgdata.toolData;
    else
        % the figure was deleted before quitting the error message box
        dlgdata.pageData{pageNum}.toolData = FcnGetDefaultToolData(dlgdata);
    end
end


%--------------------------------------------------------------------------
% FcnGetDefaultToolData writes tool data into structure
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   toolData    tool data
%--------------------------------------------------------------------------
function toolData = FcnGetDefaultToolData(dlgdata)

blockData = get_param(dlgdata.model, 'UserData');

if isfield(blockData,'toolData')
    toolData = blockData.toolData;
else
    u_min = NaN;
    u_max = u_min;
    u_0   = u_min;
    toolData.input.min = u_min;
    toolData.input.max = u_max;
    toolData.input.initial = u_0;
    if FcnChkTransferFcn(dlgdata)
        num     = tl_resolve(dlgdata.data.num.value, dlgdata.model);
        denom   = tl_resolve(dlgdata.data.denom.value, dlgdata.model);
        [Ad]    = tl_tf2ss(num,denom);
        convTol = min(cond(Ad)*1e-7,1e-2);
    else
        convTol = 1e-2;
    end
    toolData.options.convTol = sprintf('%0.3g', convTol * 100);
    toolData.options.maxTime = '5';
    toolData.options.numRecs = '0';
    toolData.options.contNum = '0';
end


%--------------------------------------------------------------------------
% FcnChkTransferFcn checks transfer function
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   ok          flag = 1, if transfer function can be evaluated, =0 otherwise
%   msg         error message
%--------------------------------------------------------------------------
function [ok,msg] = FcnChkTransferFcn(dlgdata)

ok = 1;     %#ok

% check numerator and denominator
num = tl_resolve(dlgdata.data.num.value, dlgdata.model);
den = tl_resolve(dlgdata.data.denom.value, dlgdata.model);

[Ad, Bd, Cd, Dd, msg] = tl_tf2ss(num,den);  %#ok
if isempty(Ad)
    % an error has occured
    ok = 0;
    return;
end

% check stability of the discrete transfer function
eigen_vals = eig(Ad);
mag_vals   = abs(eigen_vals);
% check to eps, because (mag_vals >= 1) leads to wrong result for
% (mag_vals(1) - 1) = -1.110223024625157e-016
if any((1 - mag_vals) < eps)
    msg = ['The transfer function has to be stable to ' ...
        'use the Transfer Function Scaling Tool.'];
    ok = 0;
end


%--------------------------------------------------------------------------
% FcnCheckHeadroom checks headroom
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   - / -
%--------------------------------------------------------------------------
function FcnCheckHeadroom(dlgdata)

toolData    = dlgdata.pageData{1}.toolData;
minHeadRoom = 0.01;

numOutputs  = dlgdata.data.output.width;
constrRange = abs(dlgdata.data.output.max-dlgdata.data.output.min);
if numOutputs && constrRange > 0
    headroomMax = abs(toolData.output.max_impl-dlgdata.data.output.max)./constrRange;
    headroomMin = abs(toolData.output.min_impl-dlgdata.data.output.min)./constrRange;
    headRoomY   = min([headroomMax; headroomMin]);
    idxY        = find(headRoomY < minHeadRoom);
else
    idxY = [];
end

if ~isempty(idxY)
    str{1} = 'There may be overflows due to numerical';
    str{2} = 'effects if input signal is near to the limits !';
    str{3} = ' ';
    str{4} = 'The current scaling results in minimum';
    str{5} = 'headroom as follows:';
    str{6} = '      Variable:                  Headroom:';
    if length(idxY) > 3
        n = 3;
    else
        n = length(idxY);
    end
    for k = 1:n
        str{length(str)+1} = ['         y(' num2str(idxY(k)) ...
            ')           =>           ' ...
            sprintf('%0.4f',headRoomY(idxY(k))*100) ' %'];
    end
    if length(idxY) > 3
        str{length(str)+1} = '         .';
        str{length(str)+1} = '         .';
        str{length(str)+1} = '         .';
    end
    ds_error_msg(str, ...
        'Title','Transfer Function Scaling Tool', ...
        'PrintMessage','no', ...
        'RegisterMessage','no');
end
